home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * dnbogl.c : an openGL-Xlib dial-and-button box program imitating the
- * behavior of the Dial & Button Confidence Test accessible
- * via the System Manager toolchest. . This is the "after"
- * version, ported from its "before" counterpart, located at
- * ../../GLX/dials+buttons/dnbglx.c
- *
- * This program creates 2 openGL visuals placed side-by-side:
- * 1. a colormap, singlebuffer'd openGL window is used to draw the
- * buttons and text area (where animation is not necessary), and
- * 2. a colormap, doublebuffer'd openGL window draws the dials
- * (smooth animation *is* needed here).
- *
- * There are 2 functions prior to the infinite loop worth noting:
- *
- * 1. openwindow() sets up the X parent (including telling the WM what
- * attributes and constraints we'd like to have), the two openGL
- * children, specifies what events each window is interested in,
- * loads the correct colormaps and then maps all three windows
- * (they will not become visible however until the first expose
- * events are generated/processed).
- *
- * 2. setupdevs() finds, opens, and creates a handle to the
- * "dial+buttons" device structure. it then determines the given
- * type and class of each device event we're going to be interested
- * in, and then makes requests to the server to send us events that
- * match the events and devices described by the event list *and*
- * that come from our specific window.
- *
- * NOTE: the functionality of the GL routine SETVALUATOR(3G) (assign
- * an initial value *and* range to a valuator) is not currently
- * implemented in any X input extension from MIT. Hence, for
- * the time being in this mixed-model imitation of the pure GL
- * dial and buttons confidence test, the dial valuator's are
- * NOT constrained in their range to only [0..1023]. This is
- * the only known discrepancy between this program and the
- * original. (There is a proposal to add this extension
- * currently being debated but it is not finalized yet.)
- *
- * Following this, the get/process input infinite loop occupies the
- * rest of the program's energies. the core of this is the "default"
- * portion of the "switch (event.type)" statement which catches the
- * dial and button events being generated. notice this is where the
- * {DnB_motion_type, DnB_press_type, DnB_release_type} vars come into
- * play: recall these were defined in setupdevs() with the 3 macros
- * DeviceMotionNotify, DeviceButtonPress, and DeviceButtonRelease,
- * respectively. XSelectExtensionEvent then was used to ask the
- * server to send us any events generated by these devices in our
- * window.
- *
- * X window functionality worth noting:
- * dnbogl implements the funtionality in its window handling of creating
- * a window the user is not allowed/able to resize utilizing the mwm
- * MotifWindowHints structure. this kind of control of what the window
- * can or can't be made to do can be useful at times.
- * Also this program automatically places the window at a specific
- * location on the console rather than letting the user interactively
- * plant it upon startup.
- * Both sets of functionality are defined in openwindow().
- *
- * IrisGL Functionality missing in OpenGL:
- * the older dial and button box commands, dbtext() and setdblights(),
- * are not supported in openGL so they are missing from this port.
- *
- * ratmandu -- ported to openGL, aug 93
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glx.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xos.h>
- #include <X11/Xatom.h>
- #include <X11/extensions/XI.h>
- #include <X11/extensions/XInput.h>
-
- #define xsize 840 /* window's "unresize-able" dimensions */
- #define ysize 480
-
- #define NumButtons 32
- #define NumDials 8
-
- #define SWITCH_OFF 0 /* button states */
- #define SWITCH_ON 1
-
- #define top 0 /* the X parent window */
- #define SBglwin 1 /* the "buttons" are drawn in a singlebuffered win */
- #define DBglwin 2 /* and the "dials" are drawn in a doublebuffer one */
- #define WINMAX 3
-
- #define BLACK 0 /* "stand-ins" for GL colormap indices */
- #define RED 1
- #define BLUE 4
- #define WHITE 7
-
- typedef struct { /* struct for each button's bottom-left origin */
- float xpos; /* (i.e. position), and whether its being pressed */
- float ypos;
- int state;
- } DB_BUTTON;
-
- DB_BUTTON but[] = { /* button positions & [initialized] state array */
- 11.0, 31.0, SWITCH_OFF,
- 16.0, 31.0, SWITCH_OFF,
- 21.0, 31.0, SWITCH_OFF,
- 26.0, 31.0, SWITCH_OFF,
- 6.0, 26.0, SWITCH_OFF,
- 11.0, 26.0, SWITCH_OFF,
- 16.0, 26.0, SWITCH_OFF,
- 21.0, 26.0, SWITCH_OFF,
- 26.0, 26.0, SWITCH_OFF,
- 31.0, 26.0, SWITCH_OFF,
- 6.0, 21.0, SWITCH_OFF,
- 11.0, 21.0, SWITCH_OFF,
- 16.0, 21.0, SWITCH_OFF,
- 21.0, 21.0, SWITCH_OFF,
- 26.0, 21.0, SWITCH_OFF,
- 31.0, 21.0, SWITCH_OFF,
- 6.0, 16.0, SWITCH_OFF,
- 11.0, 16.0, SWITCH_OFF,
- 16.0, 16.0, SWITCH_OFF,
- 21.0, 16.0, SWITCH_OFF,
- 26.0, 16.0, SWITCH_OFF,
- 31.0, 16.0, SWITCH_OFF,
- 6.0, 11.0, SWITCH_OFF,
- 11.0, 11.0, SWITCH_OFF,
- 16.0, 11.0, SWITCH_OFF,
- 21.0, 11.0, SWITCH_OFF,
- 26.0, 11.0, SWITCH_OFF,
- 31.0, 11.0, SWITCH_OFF,
- 11.0, 6.0, SWITCH_OFF,
- 16.0, 6.0, SWITCH_OFF,
- 21.0, 6.0, SWITCH_OFF,
- 26.0, 6.0, SWITCH_OFF,
- };
-
- typedef struct { /* struct for each dial's center point and */
- float xcntr; /* current angle value (0 is at 12 o'clock)*/
- float ycntr;
- int angle;
- } DB_DIAL;
-
- DB_DIAL dia[] = { /* dial positions & initialized values array */
- 10.0, 8.0, 0,
- 20.0, 8.0, 0,
- 10.0, 15.0, 0,
- 20.0, 15.0, 0,
- 10.0, 22.0, 0,
- 20.0, 22.0, 0,
- 10.0, 29.0, 0,
- 20.0, 29.0, 0,
- };
-
- /* function declarations */
- static void openwindow(char *);
- static void initGL(void);
- static void setupdevs(int *, int *, int *);
- static void makeSBwin(void);
- static void makeDBwin(void);
- void Winset(int);
- static void draw_dial(int);
- static void draw_button(int, int);
- static void makeRasterFont(Display **dpy);
- static void printString(char *s);
- static void clean_exit();
-
- static Display *dpy; /* X server connection */
- static Atom del_atom; /* WM_DELETE_WINDOW atom */
- static Window glwins[WINMAX]; /* holds X parent & 2 GL window handles */
- GLXContext glcontexts[WINMAX]; /* array for SB/DB window context ids */
-
- /* dial and buttons device event handles */
- int DnB_device_id; /* device handles for the */
- int DnB_press_type; /* DnB id, and the press, */
- int DnB_release_type; /* release, & motion */
- int DnB_motion_type; /* events they'll generate */
-
- short firstdialtouched = GL_FALSE; /* used so text for dial valuators */
- /* doesn't get drawn until the dials */
- /* actually are turned */
-
- int myExpose; /* needs to be global for makeDBwin */
- XEvent event; /* needs to be global for XIfEvent()*/
- int dialaxis[NumDials]; /* tells which dial(s) is(are) currently active */
- GLUquadricObj *qobj; /* for drawing the dials */
-
- main(int argc, char *argv[])
- {
- int myConfigure, myMotion,
- myButtPress, myButtRelease; /* track which events occur */
- int buttP[NumButtons], buttR[NumButtons]; /* track which buttons are */
- /* pressed or released */
- int i;
- int windowvisible; /* tells event handler whether or not window */
- /* is iconified--when it is, we don't want */
- /* to process any incoming events */
-
-
-
- myExpose = myConfigure = myMotion = myButtPress = myButtRelease = GL_FALSE;
-
- openwindow(argv[0]); /* configure/open up the window */
- initGL();
-
- setupdevs(buttP, buttR, dialaxis); /* set up the dial and button boxes */
- makeRasterFont(&dpy); /* make font */
-
-
- /*
- * The event loop.
- */
- while (1) { /* standard logic: get event(s), process event(s) */
-
- int axis_data[6];
-
- glFlush(); /* For proper DGL performance */
-
- /* this "do while" loop does the `get events' half of the "get events,
- * process events" action of the infinite while. this is to ensure
- * the event queue is always drained before the events that have come
- * in are processed.
- */
- do {
-
- XNextEvent(dpy, &event);
- switch (event.type) {
-
- /* "Expose" events are sort of like "REDRAW" in gl-speak in
- * terms of when a window becomes visible, or a previously
- * invisible part becomes visible.
- */
- case Expose:
- /* see if either or both of the GL windows needs redrawing.
- * this way if only one of the two is generating the event,
- * only it will get repainted.
- */
- for (i=1; i<WINMAX; i++)
- if (event.xexpose.window == glwins[i])
- myExpose |= (1 << (i-1));
- break;
-
-
- /* "ConfigNotify" events are like "REDRAW" in terms of changes
- * to a window's size or position. Since this prog locks
- * the window's size, ConfigureNotify will occur only when
- * the window gets moved.
- */
- case ConfigureNotify:
- myConfigure = GL_TRUE;
- break;
-
-
- /* "ButtonRelease" detects when LEFTMOUSE (Button1) is being
- * pressed indicating its time to leave.
- */
- case ButtonRelease:
- if (event.xbutton.button == Button1)
- clean_exit();
- break;
-
-
- /* "ClientMessage" is generated if the WM itself is being
- * gunned down and sends an exit signal to any running prog.
- */
- case ClientMessage:
- if (event.xclient.data.l[0] == del_atom)
- clean_exit();
- break;
-
-
- /* "MapNotify" is generated when the window is made visible.
- */
- case MapNotify:
- windowvisible = GL_TRUE;
- break;
-
-
- /* "UnmapNotify" is generated when the window is made "invisible"
- * --like when the window is iconified. When the window is
- * not visible (i.e. iconified), we don't want any events to
- * be processed.
- */
- case UnmapNotify:
- windowvisible = GL_FALSE;
- break;
-
-
- /* since interest is on the dNb's, they become the default.
- */
- default:
-
- if (windowvisible) { /* only process events if win is */
- /* visible (not if it's iconified) */
-
- if (event.type == DnB_motion_type) { /* dial turned */
-
- XDeviceMotionEvent *M=(XDeviceMotionEvent *)&event;
-
- if (M->deviceid == DnB_device_id) {
- i = M->first_axis; /* save out which dial */
- dialaxis[i] = GL_TRUE;/*mark current "axis" */
- dia[i].angle = M->axis_data[0];/* save angle */
- myMotion = GL_TRUE; /* set motion flag */
- } else
- fprintf(stderr,"cable has been disconnected\n");
-
- } else if (event.type == DnB_press_type) {
-
- XDeviceButtonEvent *B=(XDeviceButtonEvent *)&event;
-
- if (B->deviceid == DnB_device_id) {
- buttP[B->button-1] = GL_TRUE;/*mrk cur butpres*/
- myButtPress = GL_TRUE; /* set butpres flag */
- } else
- fprintf(stderr,"cable has been disconnected\n");
-
- } else if (event.type == DnB_release_type) {
-
- XDeviceButtonEvent *B=(XDeviceButtonEvent *)&event;
-
- if (B->deviceid == DnB_device_id) {
- buttR[B->button-1] = GL_TRUE;/*mrk cur butrel*/
- myButtRelease = GL_TRUE; /* set butrel flag */
- } else
- fprintf(stderr,"cable has been disconnected\n");
- }
- }
- break;
-
- } /* end switch (event.type) */
-
- } while (XPending(dpy)); /* end "do { } while".
- * XPending() is like qtest()--it only
- * tells you if there're any events
- * presently in the queue. it does not
- * disturb queue's contents in any way.
- */
-
-
- /* On an "Expose" event, redraw the popped, deiconified, or exposed-by-
- * another-window-being-pushed window.
- */
- if (myExpose) {
- if (myExpose & 2) {
- Winset(DBglwin); /* draw doublebufr'd window*/
- glViewport(0, 0, xsize-ysize-1, ysize-1);
- makeDBwin();
- }
- if (myExpose & 1) {
- Winset(SBglwin); /*draw singlebufr'd window*/
- glViewport(0, 0, ysize-1, ysize-1);
- makeSBwin();
- if (myButtPress) { /* check to see if button is */
- for (i=0; i<NumButtons; i++) { /* still being pressed */
- if (buttP[i])
- draw_button(i, SWITCH_ON);/* redraw pressed but */
- }
- }
- }
- myExpose = GL_FALSE; /* reset flag--queue now empty */
- }
-
- /* On a "ConfigureNotify" event, the "GL" window has been moved.
- */
- if (myConfigure) {
- Winset(DBglwin); /* draw the DB win's contents */
- makeDBwin();
- Winset(SBglwin); /* draw the SB win's contents */
- makeSBwin();
- if (myButtPress) { /* check to see if button is */
- for (i=0; i<NumButtons; i++) { /* still being pressed */
- if (buttP[i])
- draw_button(i, SWITCH_ON); /* redraw pressed butt */
- }
- }
- myConfigure = GL_FALSE; /* reset flag--queue now empty */
- }
-
- /* For a motion-type event (a dial turning), update the angle values
- * of whichever dials have just be sent to the event queue.
- */
- if (myMotion) {
- Winset(DBglwin);
- for (i=0; i<NumDials; i++) {
- firstdialtouched = GL_TRUE; /* at this point a dial is */
- draw_dial(i); /* being turned. */
- dialaxis[i] = GL_FALSE;
- }
- glXSwapBuffers(dpy, glwins[DBglwin]);
- myMotion = GL_FALSE;
- }
-
- /* For a "button press"-type event draw whichever buttons have been
- * pressed since the last time the event queue was drained.
- */
- if (myButtPress) {
- Winset(SBglwin);
- for (i=0; i<NumButtons; i++) {
- if (buttP[i])
- draw_button(i, SWITCH_ON); /* draw button being pressed */
- }
- }
-
- /* For a "button release"-type event draw whichever buttons (in "off"
- * position) have been released since last time the event q was drained.
- */
- if (myButtRelease) {
- Winset(SBglwin);
- for (i=0; i<NumButtons; i++) {
- if (buttR[i]) {
- draw_button(i, SWITCH_OFF);
- buttR[i] = GL_FALSE;
- buttP[i] = GL_FALSE;
- }
- }
- myButtPress = GL_FALSE;
- myButtRelease = GL_FALSE;
- }
- }
- }
-
-
-
- #include <Xm/MwmUtil.h>
-
-
- static int SBattributeList[] = { None };
- static int DBattributeList[] = { GLX_DOUBLEBUFFER,
- None };
-
- /* WaitForNotify:
- * used to make sure the MapWindow() calls inside openwindow() occur
- * beFORE glXMakeCurrent() is invoked so as to avoid a race condition.
- */
- static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
- return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
- }
-
-
- Colormap SBcmap, DBcmap; /* need both these handles in openwindow & initGL */
-
- /* openwindow -
- * establish connection to X server, get screen info, specify the
- * attributes we want the WM to try to provide, and create the GL windows
- */
- static void
- openwindow(char *progname)
- {
- int screen_num; /* X screen number */
- long xorig, yorig; /* window (upper-left) origin */
- XSizeHints Winhints; /* used to fix window size */
- Atom atomName; /* used to make parent */
- MotifWmHints mwm; /* win non-resizeable */
- XSetWindowAttributes SBswa, DBswa;
- XVisualInfo *SBvi, *DBvi;
-
-
-
- /* connect to the X server and get screen info */
- if ((dpy = XOpenDisplay(NULL)) == NULL) {
- fprintf(stderr, "%s: cannot connect to X server %s\n",
- progname, XDisplayName(NULL));
- exit(1);
- }
- screen_num = DefaultScreen(dpy);
-
- /* define window (upper-left) origin coords */
- xorig = (DisplayWidth(dpy, screen_num) - xsize) / 2;
- yorig = (DisplayHeight(dpy, screen_num) - ysize) / 2;
-
- /* create top level X window which will be the parent of the 2 GL windows */
- glwins[top] = XCreateSimpleWindow(dpy, RootWindow(dpy, screen_num),
- xorig, yorig, xsize, ysize, 0, 0, 0);
- if (!(glwins[top])) {
- fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
- exit(1);
- }
- /* including this call to XSelectInput shud not be necessary, but there's
- * a bug, so we have to resort to this hackaround.
- */
- XSelectInput(dpy, glwins[top], StructureNotifyMask | ButtonPressMask |
- ButtonReleaseMask | ExposureMask);
-
- /* define string that will show up in the window title bar (and icon) */
- XStoreName(dpy, glwins[top], "dial & button box confidence test");
-
- /* specify the values for the Window Size Hints we want to enforce: this
- * window can be moved but we don't want to allow any resizing to occur.
- */
- Winhints.x = xorig; /* specify desired upper-left corner origin */
- Winhints.y = yorig; /* of window so prog will place itself */
- Winhints.width = xsize; /* specify desired x/y size of window */
- Winhints.height = ysize;
- Winhints.min_width = xsize; /* set min and max width and */
- Winhints.max_width = xsize; /* height to be the same so */
- Winhints.min_height = ysize; /* window cannot be resized */
- Winhints.max_height = ysize;
- Winhints.flags = USPosition|USSize|PMaxSize|PMinSize; /* set pert. flgs */
- XSetNormalHints(dpy, glwins[top], &Winhints);
-
- /* the following, culminating with XChangeProperty, enables us to remove
- * the "[re]size" menu item from the default window menu, the "maximize"
- * control button on the window frame, and the resize handle cursors
- * that are normally available when the cursor moves into the proximity
- * of any of the window's 4 corners.
- */
- mwm.flags = MWM_HINTS_FUNCTIONS;
- /* remove the decorations from the function list we don't want to have */
- mwm.functions = MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE;
- mwm.decorations = 0;
- mwm.input_mode = 0;
- atomName = XInternAtom(dpy, _XA_MOTIF_WM_HINTS, False);
- XChangeProperty(dpy, glwins[top], atomName, atomName, sizeof(long)*8,
- PropModeReplace, (unsigned char*) &mwm, sizeof(mwm)/sizeof(long));
-
- /* now define and create the single and doublebuffer rendering windows */
-
- /* first, get the appropriate visuals */
- SBvi = glXChooseVisual(dpy, screen_num, SBattributeList);
- if (SBvi == NULL) {
- fprintf(stderr,"cudn't create a singlebuffered visual (???)\n");
- clean_exit();
- }
- DBvi = glXChooseVisual(dpy, screen_num, DBattributeList);
- if (SBvi == NULL) {
- fprintf(stderr,"cudn't create a doublebuffered visual (???)\n");
- clean_exit();
- }
-
- /* now create the appropriate GLX contexts */
- glcontexts[SBglwin] = glXCreateContext(dpy, SBvi, NULL, GL_FALSE);
- glcontexts[DBglwin] = glXCreateContext(dpy, DBvi, NULL, GL_FALSE);
-
- /* now create the two colormaps */
- SBcmap = XCreateColormap(dpy, RootWindow(dpy, SBvi->screen),
- SBvi->visual, AllocAll);
- DBcmap = XCreateColormap(dpy, RootWindow(dpy, DBvi->screen),
- DBvi->visual, AllocAll);
-
- /* now create both windows */
- SBswa.colormap = SBcmap;
- SBswa.border_pixel = 0;
- SBswa.event_mask = StructureNotifyMask | ButtonReleaseMask | ExposureMask |
- Button1MotionMask | KeyPressMask; /* express interest in events */
- glwins[SBglwin] = XCreateWindow(dpy, glwins[top],
- 0, 0, ysize, ysize,
- 0, SBvi->depth, InputOutput, SBvi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &SBswa);
- DBswa.colormap = DBcmap;
- DBswa.border_pixel = 0;
- DBswa.event_mask = StructureNotifyMask | ButtonReleaseMask | ExposureMask |
- Button1MotionMask | KeyPressMask; /* express interest in events */
- glwins[DBglwin] = XCreateWindow(dpy, glwins[top],
- ysize, 0, xsize, ysize,
- 0, DBvi->depth, InputOutput, DBvi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &DBswa);
-
- /* now map the windows--they won't be made visible until we process the
- * expose events up in main's infinite loop which these calls will
- * generate. we use XIfEvent to prevent race conditions for the children
- * SB and DB windows (which are the only ones we'll ever invoke in
- * glXMakeCurrent())
- */
- XMapWindow(dpy, glwins[DBglwin]);
- XIfEvent(dpy, &event, WaitForNotify, (char*)glwins[DBglwin]);
- XMapWindow(dpy, glwins[SBglwin]);
- XIfEvent(dpy, &event, WaitForNotify, (char*)glwins[SBglwin]);
- XMapWindow(dpy, glwins[top]); /* and finally map the X parent */
-
- /* for starters, connect the context to the singlebuffer window */
- if (!glXMakeCurrent(dpy, glwins[SBglwin], glcontexts[SBglwin]) == GL_TRUE) {
- fprintf(stderr, "error w/glXMakeCurrent: cudn't set");
- fprintf(stderr, " context to the singlebuffered GL window\n");
- exit(-1);
- }
-
- /* ensure the GL colormap is installed for this app */
- XSetWMColormapWindows(dpy, glwins[top], glwins, WINMAX);
-
- /* express interest in WM being able to kill this app */
- if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
- XSetWMProtocols(dpy, glwins[top], &del_atom, 1);
-
- glFlush();
- }
-
-
- static void
- initGL(void)
- {
- XColor colorstruct;
-
- colorstruct.pixel = BLACK; /* define colors we'll use */
- colorstruct.red = 0;
- colorstruct.green = 0;
- colorstruct.blue = 0;
- colorstruct.flags = DoRed | DoGreen | DoBlue;
- XStoreColor(dpy, SBcmap, &colorstruct);
- XStoreColor(dpy, DBcmap, &colorstruct);
- colorstruct.pixel = RED;
- colorstruct.red = 65535;
- colorstruct.green = 0;
- colorstruct.blue = 0;
- colorstruct.flags = DoRed | DoGreen | DoBlue;
- XStoreColor(dpy, SBcmap, &colorstruct);
- XStoreColor(dpy, DBcmap, &colorstruct);
- colorstruct.pixel = BLUE;
- colorstruct.red = 0;
- colorstruct.green = 0;
- colorstruct.blue = 65535;
- colorstruct.flags = DoRed | DoGreen | DoBlue;
- XStoreColor(dpy, SBcmap, &colorstruct);
- XStoreColor(dpy, DBcmap, &colorstruct);
- colorstruct.pixel = WHITE;
- colorstruct.red = 65535;
- colorstruct.green = 65535;
- colorstruct.blue = 65535;
- colorstruct.flags = DoRed | DoGreen | DoBlue;
- XStoreColor(dpy, SBcmap, &colorstruct);
- XStoreColor(dpy, DBcmap, &colorstruct);
-
- qobj = gluNewQuadric(); /* define basics for dial drawing */
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
- Winset(DBglwin); /* define DB win's orthographic project */
- glLoadIdentity();
- gluOrtho2D(0.0, 30.0, 0.0, 40.0);
-
- Winset(SBglwin); /* define SB win's orthographic project */
- glLoadIdentity();
- gluOrtho2D(0.0, 40.0, 0.0, 40.0);
-
- glFlush();
- }
-
-
- /* setupdevs -
- *
- * establish a live connection to the dial+buttons device.
- *
- * leverages off the "X11 Input Extension Library Specification"
- * document (you *shud* be able to locate the on-line public access
- * directory which contains all the files to print hard-copy of this
- * document under .../mit/doc/extensions/xinput). refer to
- * /usr/include/X11/extensions/{XI.h, XInput.h} for structures accessed.
- */
- static void
- setupdevs(int buttP[NumButtons], int buttR[NumButtons], int dialaxis[NumDials])
- {
- int i, ndevices;
- XDevice *DnB_device;
- XDeviceInfoPtr lp, list;
- int num_ext_event_classes;
- XEventClass ListOfEventClass[3];
- int DnB_press_class, DnB_release_class, DnB_motion_class;
-
-
- /* get a ptr to the list of all currently defined input devices */
- list = (XDeviceInfoPtr) XListInputDevices(dpy, &ndevices);
- if (!list) {
- fprintf(stderr,"XlistInputDevices failed to generate a devices list\n");
- exit(1);
- }
-
- /* check out the /usr/people/4Dgifts/examples/devices/input/X/Xlist.c
- * program (which gets compiled into "xlist"). running it will list
- * all the currently available input devices on the machine xlist is
- * run on. there is a LOT that should be studied in the "input" subtree.
- */
- for (lp=list, i=0; i<ndevices; lp++, i++) {
- if (lp->use==IsXExtensionDevice && strcmp(lp->name,"dial+buttons")==0) {
- break; /* found the right one--now save the ptr (lp) to it */
- }
- }
- if (i == ndevices) {
- fprintf(stderr, "\"dial+buttons\" device was not found\n");
- exit(1);
- }
- DnB_device = XOpenDevice(dpy, lp->id); /* open the DnB device */
- if (!DnB_device) {
- fprintf(stderr, "XOpenDevice failed for \"dial+buttons\" device\n");
- exit(1);
- }
- DnB_device_id = DnB_device->device_id; /* save out the device id */
-
- /* the following 3 macros determine the given event's type and class.
- * each macro is passed the structure that describes the device from
- * which input is desired.
- */
- DeviceButtonPress(DnB_device, DnB_press_type, DnB_press_class);
- DeviceButtonRelease(DnB_device, DnB_release_type, DnB_release_class);
- DeviceMotionNotify(DnB_device, DnB_motion_type, DnB_motion_class);
-
- ListOfEventClass[0] = DnB_press_class;
- ListOfEventClass[1] = DnB_release_class;
- ListOfEventClass[2] = DnB_motion_class;
-
- num_ext_event_classes = 3;
-
- /* XSelectExtensionEvent requests the server to send events that match
- * the events and devices described by the event list and that come
- * from the requested window.
- * first, we'll put in our button press/release requests for the
- * single-buffered (buttons and text) GL window.
- */
- XSelectExtensionEvent(dpy, glwins[SBglwin],
- ListOfEventClass, num_ext_event_classes);
-
- /* now we'll request the Motion events for the double-buffered (dials)
- * GL window.
- * note that in each of these two invocations of XSelectExtensionEvent,
- * we're selecting all three event classes in each window. this is
- * because, no matter where the cursor is inside the window containing
- * both the single and double -buffered GL windows, we want to process
- * dial or button events, whether or not the mouse is physically
- * present in either of these two respective windows.
- */
- XSelectExtensionEvent(dpy, glwins[DBglwin],
- ListOfEventClass, num_ext_event_classes);
-
- /* initialize all the buttons and dial "markers" to indicate none have
- * yet been pressed or moved.
- */
- for (i=0; i<NumButtons; i++) {
- buttP[i]=GL_FALSE;
- buttR[i]=GL_FALSE;
- }
- for (i=0; i<NumDials; i++) {
- dialaxis[i]=GL_FALSE;
- }
- }
-
-
-
- char *typeToName[] = {
- "Colormap single buffer",
- "Colormap double buffer",
- };
-
-
- /* A little helper wrapper for glXMakeCurrent.
- * passes the index to jointly access the windows and contexts array and
- * checks the return value. This makes the call to begin GL drawing a
- * little simpler. Building in such automatic error checking is always a
- * "smooth move" (*not* like the cancerously-mutant human with the enlarged
- * proboscis plastered all over the place urging people to be likewise
- * smoothly cancerous and hardly cool).
- */
- void
- Winset(int type)
- {
- int rv;
-
- XSync(dpy,GL_FALSE);
- rv = glXMakeCurrent(dpy, glwins[type], glcontexts[type]);
- if (rv == GL_FALSE) {
- fprintf(stderr, "glXMakeCurrent failed for a %s-type window\n",
- typeToName[type]);
- exit(-1);
- }
- }
-
-
-
- /* makeSBwin -- Draw the buttons and text in the singlebuffer'd GL window
- */
- static void
- makeSBwin(void)
- {
- int i;
-
-
- glClearIndex(WHITE); /* clear the window */
- glClear(GL_COLOR_BUFFER_BIT); /* background to white */
-
- for (i=0; i<NumButtons; i++)
- draw_button(i, SWITCH_OFF); /* draw the buttons */
-
- glIndexi(BLACK);
- glRasterPos2i(2, 1); /* "charstr()" replacement draws text */
- printString("Use left mouse button to quit."); /* in lower left corner */
- }
-
-
- /* makeDBwin -- Draw the dials in the doublebuffer'd GL window
- */
- static void
- makeDBwin(void)
- {
- int i;
-
-
- glClearIndex(WHITE); /* clear the window */
- glClear(GL_COLOR_BUFFER_BIT); /* background to white */
-
- for (i=0; i<NumDials; i++)
- draw_dial(i); /* and draw the dials */
-
- glXSwapBuffers(dpy, glwins[DBglwin]);
-
- if (myExpose) { /* if an Expose is being */
- glClearIndex(WHITE); /* processed, go ahead & */
- glClear(GL_COLOR_BUFFER_BIT); /* draw the whole new */
- for (i=0; i<NumDials; i++) /* back-buffer with what */
- draw_dial(i); /* we just swaped into */
- glXSwapBuffers(dpy, glwins[DBglwin]); /* the present front */
- } /* (visible) buffer */
- }
-
-
-
- /* draw_dial -- Draw dial number dia[0...7]
- */
- static void
- draw_dial(int dialnum)
- {
- DB_DIAL *dptr = &dia[dialnum];
- float xcenter, ycenter;
- int angle;
- char str[80];
-
-
- xcenter = dptr->xcntr;
- ycenter = dptr->ycntr;
- angle = dptr->angle;
-
- if ((firstdialtouched) && /* when we know a dial has */
- (dialaxis[dialnum])) { /* actually been turned, update */
- Winset(SBglwin); /* the text area that resides in */
- glIndexi(WHITE); /* the singlebuffer'd GL window */
- glRecti(2, 2, 24, 5);
- sprintf(str,"Dial %d intensity is %d",dialnum,angle);
- glIndexi(BLUE);
- glRasterPos2i(2, 3);
- printString(str);
- glFlush();
- }
-
- Winset(DBglwin); /* now switch cur gfx context to */
- angle = (dptr->angle * 3600) >> 10; /* doublebuffer'd window & update*/
- glIndexi(WHITE); /* dial currently being turned: */
- glPushMatrix(); /* FIRST: "white-out" the entire*/
- glTranslatef(xcenter, ycenter, 0.0);
- gluDisk(qobj, 0.0, 2.5, 32, 1);
- glPopMatrix();
- glIndexi(BLACK);
- glPushMatrix();
- glTranslatef(xcenter, ycenter, 0.0);
- gluDisk(qobj, 2.4, 2.5, 32, 1);
- glPopMatrix();
- glIndexi(RED);
- glPushMatrix();
- glTranslatef(xcenter, ycenter, 0.0);
- gluPartialDisk(qobj, 0.0, 2.5, 32, 1, 0.0, angle*0.1);
- glPopMatrix();
-
- glFlush();
- }
-
-
- #define BSIZE 3.0
-
- /* draw_button -- Draw button number buttno in its on or off state
- */
- static void
- draw_button(int buttno, int state)
- {
- DB_BUTTON *bptr = &but[buttno];
- unsigned long button_led = 0;
- float xpos, ypos;
- char str[80];
-
-
- xpos = bptr->xpos;
- ypos = bptr->ypos;
-
- if (state == SWITCH_ON) {
- glIndexi(WHITE); /* white out the text area to */
- glRecti(2, 2, 24, 5); /* prepare for new button press */
-
- sprintf(str, "Button %d is being pressed", buttno);
- glIndexi(BLUE);
- glRasterPos2i(2, 3); /* update text string in bottom- */
- printString(str); /* -left corner of the SB window */
-
- /* now draw button being pressed in RED--have to resort to a hack here:
- * in older IrisGL, cmds like rect rendered "bloated" polygons where an
- * outline would be made around the area to be filled and then the
- * outline would be drawn over as well. In the current point-sampled
- * approach, two adjacent sides do NOT get drawn over, thus the need to
- * do a WHITE glRecti first with each edge being expanded away from the
- * center by 1 pixel. (to observe the difference, comment out the next
- * two lines and see the differing results.)
- */
- glIndexi(WHITE);
- glRecti(xpos-1, ypos-1, xpos+BSIZE+1, ypos+BSIZE+1);
- glIndexi(RED);
- glRecti(xpos, ypos, xpos+BSIZE, ypos+BSIZE);
-
- } else {
- glIndexi(WHITE);
- glRecti(2, 2, 24, 5); /* white out area where text was */
- glRecti(xpos, ypos, xpos+BSIZE, ypos+BSIZE);
- glPolygonMode(GL_FRONT, GL_LINE); /* now draw in "outline" mode to */
- glIndexi(BLACK); /* draw an unpressed button, and */
- glRecti(xpos, ypos, xpos+BSIZE, ypos+BSIZE); /* when we're finished */
- glPolygonMode(GL_FRONT, GL_FILL); /* return to "fill"/default mode */
- }
-
- }
-
-
- /* makeRasterFont() and printString() are lifted out of font.c (lives in
- * this same directory) as a replacement to the IrisGL charstr() function.
- */
- GLuint base;
-
- static void makeRasterFont(Display **dpy)
- {
- XFontStruct *fontInfo;
- Font id;
- unsigned int first, last;
-
- fontInfo = XLoadQueryFont(*dpy,
- "-sgi-screen-bold-r-normal--15-150-72-72-m-90-iso8859-1");
- if (fontInfo == NULL) {
- printf("no font found\n");
- exit(0);
- }
- id = fontInfo->fid;
- first = fontInfo->min_char_or_byte2;
- last = fontInfo->max_char_or_byte2;
- base = glGenLists(last+1);
- if (base == 0) {
- printf("out of display lists\n");
- exit(0);
- }
- glXUseXFont(id, first, last-first+1, base+first);
- }
-
-
- static void printString(char *s)
- {
- glPushAttrib(GL_LIST_BIT);
- glListBase(base);
- glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
- glPopAttrib();
- }
-
-
- /* clean_exit -- Clean up before exiting
- */
- static void
- clean_exit(void)
- {
- XCloseDisplay(dpy);
- exit(0);
- }
-